#pragma once

#include "Log.hpp"
#include "Sock.hpp"
#include "Deamon.hpp"
#include <functional>
#include <cassert>
#include <pthread.h>
#include <unistd.h>
#include <signal.h>

namespace ns_tcpserver
{
    class Server;

    struct threadData
    {
        int _sock;
        Server *_ptr_server;

        threadData(int sock, Server *ptr_server)
            : _sock(sock), _ptr_server(ptr_server)
        { }
    };

    class Server
    {
    private:
        typedef std::function<void(int)> func_t;

        static void *threadRoutine(void *args)
        {
            pthread_detach(pthread_self()); // 线程分离自身
            threadData *pth = static_cast<threadData *>(args);
            Server *pthis = pth->_ptr_server;
            pthis->_func(pth->_sock);
            close(pth->_sock);
            delete pth;
            return nullptr;
        }

    public:
        Server(uint16_t port, const std::string ip = "0.0.0.0")
            : _listenSock(-1), _port(port), _ip(ip)
        {
        }

        // 绑定服务函数
        void BindServer(func_t func)
        {
            _func = func;
        }

        // 服务端初始化函数
        void init()
        {
            // 创建socket套接字
            _listenSock = _sock.Socket();
            if (_listenSock < 0)
            {
                exit(2);
            }

            // 绑定
            if (_sock.Bind(_listenSock, _ip, _port) < 0)
            {
                exit(3);
            }

            // 设置监听状态
            if (_sock.Listen(_listenSock, 20) < 0)
            {
                exit(4);
            }

            logMessage(NORMAL, "server init success!\n");
        }

        // 服务器运行函数
        void start()
        {
            // MyDaemon();  

            signal(SIGPIPE, SIG_IGN);
            std::string cli_ip; // 客户端ip
            uint16_t cli_port;  // 客户端端口号

            while (true)
            {
                // 接受连接
                int sock_cli = _sock.Accept(_listenSock, &cli_ip, &cli_port);
                if (sock_cli < 0)
                {
                    exit(5);
                }

                // 创建一个线程，执行服务器函数
                threadData *pth = new threadData(sock_cli, this);
                assert(pth);

                pthread_t tid;
                int n = pthread_create(&tid, nullptr, threadRoutine, (void *)pth);
                assert(n == 0);
                (void)n;
            }
        }

    private:
        ns_sock::Sock _sock; // 套接字对象
        int _listenSock;     // 监听套接字
        uint16_t _port;      // 端口号
        std::string _ip;     // IP地址
        func_t _func;        // 服务器启动后执行的函数
    };
}